<?php

// $Id$

/**
 * @file
 * Special functions for install.
 */
class ResMania_Install_Model {

    private $_overrideVersion = false; // override version: production this should be = false;
    
    private $_installerVersion = "1.2.1";
    private $_coreConfigURL = "http://distro.resmania.com/config.json";
    private $_disto_point = "http://distro.resmania.com/";
    private $_ionCube_coreURL = "/ioncube_core.zip";
    private $_coreURL = "/core.zip";
    private $_zendFrameworkMinVersion = "1.9.5";

    /*
     * Performs the checks and returns the results.
     *
     * return js array
     */

    function resmania_checks() {
        $php = $this->resmania_checkphp('5.2.5');
        $folder = $this->resmania_check_directory(); // 2 = ok, 0 = cant create, 1 = already exisit
        $inno_db = $this->resmainia_check_db();
        $php_directives = $this->resmania_checkPHPdirectives();
        if (!extension_loaded('zlib')) {
            $zlib_support = FALSE;
        } else {
            $zlib_support = TRUE;
        }
        if (!extension_loaded('pdo_mysql')) {
            $pdo_support = FALSE;
        } else {
            $pdo_support = TRUE;
        }
        $array = array('php' => $php, 'folder' => $folder, 'db' => $inno_db, 'phpdirectives' => $php_directives, 'pdosupport' => $pdo_support, 'zlibsupport' => $zlib_support);
        return $array;
    }

    /*
     * Check the php version
     */

    function resmania_checkphp($v) {
        if (function_exists('version_compare') == FALSE) {
            return FALSE;
        }
        $phpcheck = version_compare(PHP_VERSION, $v, '>=');
        if ($phpcheck == TRUE) {
            $phpversion = "Ok";
        } else {
            $phpversion = "Failed";
        }
        return $phpcheck;
    }

    function resmania_check_directory() {

        $resmania_folder = 'RM';

        // for existing RM folder
        if (file_exists($resmania_folder)) {
            if (file_exists($resmania_folder . "/system/application/classes/RM/Connector.php")) {
                if (is_writable($resmania_folder)) {
                    return 1;
                } else {
                    return 0;
                }
            } else {
                if (is_writable($resmania_folder)) {
                    return 2;
                } else {
                    return 0;
                }
            }
        } else {
            // for new RM folder

            if (mkdir($resmania_folder, 0755)) {
                return 2;
            } else {
                return 0;
            }
        }
    }

    /*
     * This will return the DB support
     *
     * return   boolean     true = ok
     */

    function resmainia_check_db() {
        $query = "CREATE TABLE  {RM_db_check} (test TINYINT( 1 ) NOT NULL) ENGINE = INNODB";
        $result = db_query($query);
        if ($result == FALSE) {
            $inno_db = FALSE;
        } else {
            $inno_db = TRUE;
        }
        $query = "DROP TABLE {RM_db_check}";
        $result = db_query($query);
        return $inno_db;
    }

    /*
     * this is used to check anything that could be a problem
     */

    function resmania_checkPHPdirectives() {

        // first of all see if we can add an override (this depends on safe mode)
        // but it is worth a try... (600 = 10 mins)
        //  ini_set('max_execution_time', 600);
        //  ini_set('max_input_time', 600);
        // now check the values...
        $failed = 0;
        if ((int) ini_get('max_execution_time') < 240)
            $failed += 1;
        if ((int) ini_get('max_input_time') < 240)
            $failed += 1;
        if ((int) trim(ini_get('memory_limit'), "Mm") < 32)
            $failed += 1;

        if ($failed > 0) {
            //return FALSE;
            return 'NO';
        } else {
            //return TRUE;
            return 'YES';
        }
    }

    function resmania_download() {

        $destination = 'RM/core.zip';
        @unlink($destination);
        $version = $this->resmania_getLatestVersion();

        $sourceSizePath = $this->_disto_point."d.php?d=".base64_encode( '{"d": "'.$_SERVER['SERVER_NAME'].'", "l": "'.$_GET['key'].'", "v":"'.$version.'","p": "core", "qt": "size"}');
        $sourceSize = @file_get_contents($sourceSizePath);
        if ($sourceSize === "false"){
            return array('success'=>FALSE, 'msg'=>'License Invalid, please refresh this page to re-enter license key. If you are experiencing problems please contact ResMania Customer Services or if you require a license key please purchase a key from resmania.com');
        }

        $source = $this->_disto_point."d.php?d=".base64_encode( '{"d": "'.$_SERVER['SERVER_NAME'].'", "l": "'.$_GET['key'].'", "v":"'.$version.'","p": "core"}');

        watchdog('ResMania', t("Source set as: $this->_disto_point"), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
        watchdog('ResMania', t("Destination set as: $destination"), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);

        $this->resmania_setSourceSize($sourceSize);

        $_SESSION['licenseKey'] = $_GET['key'];

        $copy_result = FALSE;
        if (function_exists('copy')) { // check this is enabled
            $copy_result = copy($source, $destination);
        } else {
            $copy_result = $this->resmania_fileDownload($source, $destination);
        }
        if ($copy_result) {
            $copy_result_msg = "Ok";
        } else {
            $copy_result_msg = "Failed";
        }
        watchdog('ResMania', t("Copy Result: $copy_result_msg"), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);

        $source_size = (float) $_SESSION['sourceFileSize'];
        $desination_size = (float) filesize($destination);

        if ($copy_result || ($source_size == $desination_size)) {
            watchdog('ResMania', t("Copy completed ok"), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
            return array('success'=>TRUE, 'msg'=>'');
        } else {
            watchdog('ResMania', t("System cannot copy ResMania core file"), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
            return array('success'=>FALSE, 'msg'=>'Download Failed');
        }
    }

    function clearCoreZip() {
        $destination = 'RM/core.zip';
        @unlink($destination);
    }

    function resmania_getLatestVersion() {
        
        if ($this->_overrideVersion){
            return $this->_overrideVersion;
        }
        
        $config_json = @file_get_contents($this->_coreConfigURL);
        $version = "lastversion"; // this is the folder where the fallback version is stored.
        if (isset($config_json)) {
            $config = json_decode($config_json);
            if (isset($config->version)) {
                $version = $config->version;
            }
        }

        return trim($version);
    }

    /*
     * Substitute for PHP Copy
     */

    function resmania_fileDownload($source, $destination) {
        $rh = fopen($source, 'rb');
        $wh = fopen($destination, 'wb');
        if ($rh === FALSE || $wh === FALSE) {
            // error reading or opening file
            return FALSE;
        }
        while (!feof($rh)) {
            if (fwrite($wh, fread($rh, 1024)) === FALSE) {
                // 'Download error: Cannot write to file ('.$file_target.')';
                return FALSE;
            }
        }
        fclose($rh);
        fclose($wh);
        // No error
        return TRUE;
    }

    /*
     *  Get filesize of remote files.
     */

    function resmania_get_remote_file_size($url, $readable = TRUE) {
        $parsed = parse_url($url);
        $host = $parsed["host"];
        $fp = @fsockopen($host, 80, $errno, $errstr, 20);
        if (!$fp)
            return FALSE;
        else {
            @fputs($fp, "HEAD $url HTTP/1.1\r\n");
            @fputs($fp, "HOST: $host\r\n");
            @fputs($fp, "Connection: close\r\n\r\n");
            $headers = "";
            while (!@feof($fp)
                )$headers .= @ fgets($fp, 128);
        }
        @fclose($fp);
        $return = FALSE;
        $arr_headers = explode("\n", $headers);
        foreach ($arr_headers as $header) {
            // follow redirect
            $s = 'Location: ';
            if (substr(strtolower($header), 0, strlen($s)) == strtolower($s)) {
                $url = trim(substr($header, strlen($s)));
                return get_remote_file_size($url, $readable);
            }

            // parse for content length
            $s = "Content-Length: ";
            if (substr(strtolower($header), 0, strlen($s)) == strtolower($s)) {
                $return = trim(substr($header, strlen($s)));
                break;
            }
        }
        if ($return && $readable) {
            $size = round($return / 1024, 2);
            $sz = "KB"; // Size In KB
            if ($size > 1024) {
                $size = round($size / 1024, 2);
                $sz = "MB"; // Size in MB
            }
            $return = "$size $sz";
        }
        return $return;
    }

    /*
     * Sets and Stores the Source FileSize
     * This is only called at the start to set the value
     */

    function resmania_setSourceSize($sourceSize) {

        if (isset($_SESSION['sourceFileSize'])) {
            unset($_SESSION['sourceFileSize']);
        } //clear it, if it's found

        $_SESSION['sourceFileSize'] = $sourceSize; // set the new value

        watchdog('Resmania', t("Source File Size: $sourceSize"), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
        watchdog('Resmania', t("Session Saved Source File Size: $sourceSize"), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
    }

    /*
     * Unzip the core
     */

    function resmania_unzip_core() {
        $source = "RM/core.zip";
        $unzip_destination = 'RM';
        watchdog('Resmania', t("Unzip Destination: $unzip_destination"), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
        if (file_exists($unzip_destination)) {
            watchdog('Resmania', t("/RM folder already exists"), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
            $folder_create_result = TRUE;
        } else {
            $folder_create_result = mkdir($unzip_destination);
            watchdog('Resmania', t("Folder Creation Result $folder_create_result"), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
        }
        if (!$folder_create_result) {
            watchdog('Resmania', t('System cannot create a folder: ' . $unzip_destination . ' for Resmania core'), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
            return FALSE;
        }
        watchdog('Resmania', t('Unzip Started'), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);

        $unzip_result = $this->resmania_unpack_zip($source, $unzip_destination);
        watchdog('Resmania', t("Unzip Result: $unzip_result"), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);

        if (!$unzip_result) {
            watchdog('Resmania', t('System cannot unzip:' . $source . ' to ' . $unzip_destination), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
            return FALSE;
        } else {
            watchdog('Resmania', t('Unzip Finished'), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
            return TRUE;
        }
    }

    /*
     * Unzip file
     */

    function resmania_unpack_zip($source, $destination) {
        $pclzip_path = drupal_get_path('module', 'resmania') . '/inc/pclzip.lib.php';
        require_once($pclzip_path);
        $zip = new PclZip($source);
        if ($zip->extract(PCLZIP_OPT_PATH, $destination) == 0) {
            watchdog('Resmania', t("File Extraction Failed: errorcode: " . $zip->errorInfo(true)), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
            return FALSE;
        }
        watchdog('Resmania', t("File Extraction Complete Ok"), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
        return TRUE;
    }

    /*
     * This completes the DB installation
     */

    function resmania_setup_db() {
        $path = 'RM';
        $sqlfile = 'RM/system/sql/install.sql';
        watchdog('Resmania', t("Database Setup Started"), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
        $filecontents = file_get_contents($sqlfile);
        if ($filecontents != "") {
            $queries = $this->resmania_split_sql($filecontents);

            if (!empty($queries)) {
                foreach ($queries as $query) {
                    //$result = db_query($query);
                    //use low-level query, if use function db_query() '{' or '}' is not work;
                    $result = $this->resmania_db_query($query);
                    if (!$result['success']) {
                        watchdog('Resmania', t($result['error']), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
                        watchdog('Resmania', t("SQL Query @query has error"), $variables = array('@query' => $query), $severity = WATCHDOG_NOTICE, $link = NULL);
                        watchdog('Resmania', t('The database installation has failed!'), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
                        return FALSE;
                    }
                }
            }
        }

        if ($_SESSION['licenseKey']!==""){
            $this->resmania_db_query("UPDATE  `rm_config` SET  `value` = '".$_SESSION['licenseKey']."' WHERE  `rm_config`.`id` =  'rm_config_licensekey'");
        }
        watchdog('Resmania', t('The database installation complete!'), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);
        return TRUE;
    }

    /**
     * @param string
     * @return array
     */
    function resmania_split_sql($sql) {
        $sql = trim($sql);

        //Remove comments
        $sql = preg_replace("/\n\#[^\n]*/", '', $sql);
        $sql = preg_replace("/^--[^\n]*/", '', $sql); //First comment
        $sql = preg_replace("/\n--[^\n]*/", '', $sql);

        //Remove 'tabs'
        $sql = preg_replace("/\t/", '', $sql);

        $buffer = array();
        $ret = array();
        $in_string = false;

        for ($i = 0; $i < strlen($sql) - 1; $i++) {
            if ($sql[$i] == ";" && !$in_string) {
                $ret[] = trim(substr($sql, 0, $i));
                $sql = substr($sql, $i + 1);
                $i = 0;
            }

            if ($in_string && ($sql[$i] == $in_string) && $buffer[1] != "\\" && ($sql[$i] != "'" || $sql[$i - 1] != "'" || $sql[$i - 2] != "\\")) {
                $in_string = false;
            } elseif (
                    !$in_string
                    && ($sql[$i] == '"' || $sql[$i] == "'")
                    && (!isset($buffer[0]) || $buffer[0] != "\\")
            ) {
                $in_string = $sql[$i];
            }

            if (isset($buffer[1])) {
                $buffer[0] = $buffer[1];
            }
            $buffer[1] = $sql[$i];
        }

        if (!empty($sql)) {
            $ret[] = trim($sql);
        }
        return ($ret);
    }

    function resmania_post_check() {

        // 1. check the correct folders are writable within the RM folder
        $path = 'RM';

        // all writable folders...
        $writeable_folders = array(
            $path . '/userdata/temp',
            $path . '/userdata/images/media',
            $path . '/userdata/images/units',
            $path . '/userdata/logs',
            $path . '/userdata/languages',
            $path . '/userdata/backups',
            $path . '/userdata/modules',
            $path . '/userdata/plugins'
        );
        // now loop through each folder and check if they are writable
        $folder_check = TRUE;
        foreach ($writeable_folders as $folder) {
            if (!is_writable($folder)) {
                $folder_check = FALSE;
            }
        }

        $array = array('folderCheck' => $folder_check);
        watchdog('Resmania', json_encode($array), $variables = array(), $severity = WATCHDOG_NOTICE, $link = NULL);

        return $array;
    }

    /*
     * run a query, unfortunalty Drupal7 does not support inserts for SQL so we have to setup using this process
     */

    function resmania_db_query($query) {
        //return db_query($query); // this does not work because drupal removed "{}"
        
        global $dbConnection;

        if (!is_resource($dbConnection->active_db)){
            // make the db connection
            $dbConnection = $this->_dbConnect($dbConnection);
            if (!$dbConnection){
                return false;
            }
        }

        // default (good return)
        $result = array("success"=>true, "error" => "");

        switch ($dbConnection->db_type) {
            case 'mysqli' :
                mysqli_select_db($dbConnection->active_db,$dbConnection->database);
                mysqli_query($dbConnection->active_db, $query) or $result = array("success"=>false, "error" => mysqli_error());
                return $result;
                break;
            case 'mysql' :
                mysql_select_db($dbConnection->database, $dbConnection->active_db);
                mysql_query($query, $dbConnection->active_db) or $result = array("success"=>false, "error" => mysql_error());
                return $result;
                break;
        }
    }

    /**
     * Connect to the Drupal DB
     * 
     * @param array $dbConnection
     * @return array
     */
    private function _dbConnect($dbConnection){
        
        $active_db = Database::getConnection();
        $dbconnection = $active_db->getConnectionOptions();
        $db_type = $dbconnection['driver'];
        $username = $dbconnection['username'];
        $password = $dbconnection['password'];
        $server = $dbconnection['host'];
        $database = $dbconnection['database'];
        
        $dbConnection->db_type = $db_type;
        $dbConnection->database = $database;

        switch ($db_type){
            case 'mysqli' :
                $dbConnection->active_db = mysqli_connect($server,$username,$password,$database);
                return $dbConnection;
                break;
            case 'mysql' :
                $dbConnection->active_db = mysql_connect($server,$username,$password,$database);
                return $dbConnection;
                break;
            case 'pgsql':
                // we don't currently support PostgreSQL
                return false;
                break;
        }
    }
}
